﻿#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <limits.h>
#if defined(WIN32) || defined(WIN64)
#include "windows.h"
#endif

#include "define.h"
#include <curl/curl.h>
#include "iota.h"
#include "cjson/cJSON.h"
#include "zlog.h"
#include "iniparser.h"
#include "http.h"
#include "BussinessTerminalManage.h"
#include "iota.h"
#include "microApp.h"
#include "common.h"
#include <execinfo.h> 

char LogLevel[32];
dictionary *ini;
dictionary *iniMqtt;
dictionary *iniRule;
char path[256];
extern Snowflake sf;
extern ST_MODEL_CTL g_st_model_ctl;

void wiat_for_signal()
{
	printf("wiat_for_signal...\n");
	sleep(60);
}

int get_current_md5(char* md5_buf) {
	FILE* fp = popen("iptables -S | md5sum | cut -d' ' -f1", "r");
	if (!fp) return -1;

	// 读取纯粹的MD5值（32字符）
	if (fgets(md5_buf, 33, fp) == NULL) {
		pclose(fp);
		return -1;
	}
	pclose(fp);
	// 去除可能的换行符
	md5_buf[strcspn(md5_buf, "\n")] = 0;
	return 0;
}

void *self_checking_thread(void *param)
{
	dzlog_info("self_checking_thread start...");
	pthread_detach(pthread_self());
	pthread_setname_np(pthread_self(), "checking");

	int result = system("ps -ef");
	if (result == 0)
	{
		printf("ps -ef ok\n");
		dzlog_info("ps -ef ok");
	}
	else
	{
		printf("ps -ef not found \n");
		dzlog_info("ps -ef not found");
	}

	FILE *fp = NULL;
	char buf[256];
	int s4g = 0;
	if ((fp = popen("wwan at send AT+CGMI dev ppp0", "r")) != NULL)
	{
		while (fgets(buf, 255, fp) != NULL)
		{
			char* p = strstr(buf, "OK");
			if (p)
			{
				s4g = 1;
			}
		}
	}
	if (s4g)
	{
		g_st_model_ctl._4gModules = 1;
	}
	else
	{
		g_st_model_ctl._4gModules = 0;
	}
	if (fp != NULL)
	{
		fclose(fp);
	}
	else
	{
		dzlog_info("fp is NULL");
	}

	result = system("appm -V");
	if (result == 0)
	{
		dzlog_info("appm -V [ok]");
		g_st_model_ctl.appModules = 1;
	}
	else
	{
		dzlog_info("appm -V not found");
		g_st_model_ctl.appModules = 0;
	}

	sleep(30);
	char current_md5[33] = { 0 };
	char last_md5[33] = { 0 };
	if (get_current_md5(last_md5) == 0) {
		printf("初始MD5: %s\n", last_md5);
	}

	while (1) {
		if (get_current_md5(current_md5) == 0) {
			if (strcmp(current_md5, last_md5) != 0) {
				dzlog_info("iptables change");
				system("iptables -S > ./conf/iptables_bak.txt");
				strcpy(last_md5, current_md5);
			}
		}
		else {
			printf("获取MD5失败\n");
		}
		sleep(5);
	}
}

void iotInfo_thread()
{
	dzlog_info("iotInfo_thread start");
	check_and_report_iot_changes();
}

/// @brief 信号处理函数
/// @param signo 信号
void sig_handler(int signo)
{
	setstatus(0);
	system("iptables -S > ./conf/iptables_bak.txt");
	dzlog_info("sig_handler");
	FILE *fp = fopen("/tmp/EagleEyeSMG.pid", "w");
	if (fp == NULL)
	{
		dzlog_error("open file error");
		exit(1);
	}

	//信号分类总结
	//信号		编号	类型		默认行为		可否捕获
	//SIGINT	2		用户中断	终止			是
	//SIGILL	4		程序错误	终止 + 核心转储	是
	//SIGFPE	8		程序错误	终止 + 核心转储	是
	//SIGSEGV	11		程序错误	终止 + 核心转储	是
	//SIGTERM	15		终止请求	终止			是
	//SIGABRT	6		程序错误	终止 + 核心转储	是
	if (signo == SIGINT)//pee有测试出来
	{
		/*
		1.用户在终端按下 Ctrl+C
		2.键盘中断请求
		*/
		fprintf(fp, "interrupt|%d", time(NULL));
		dzlog_info("sig_handler SIGINT");			
	}
	else if (signo == SIGILL)//未测试触发过
	{
		/*
		1.执行非法或未定义的机器指令
		2.代码损坏或错误的函数指针调用
		3.硬件不支持的指令
		*/
		fprintf(fp, "codedump|%d", time(NULL));
		dzlog_info("sig_handler SIGILL");
	}
	else if (signo == SIGFPE)
	{
		/*
		1.除以零
		2.浮点溢出/下溢
		3.无效的浮点操作
		*/
		fprintf(fp, "codedump|%d", time(NULL));
		dzlog_info("sig_handler SIGFPE");
	}
	else if (signo == SIGSEGV)//pee已触发，触发测试代码int* ptr = NULL;*ptr = 42;
	{
		/*
		1.访问无效内存地址
		2.访问只读内存区域
		3.栈溢出
		4.使用已释放的内存
		*/
		fprintf(fp, "codedump|%d", time(NULL));
		dzlog_info("sig_handler SIGSEGV");
	}
	else if (signo == SIGTERM)//
	{
		/*
		1.kill 命令的默认信号
		2.系统关闭(系统重启)
		3.进程管理器请求终止
		*/
		fprintf(fp, "interrupt|%d", time(NULL));
		dzlog_info("sig_handler SIGTERM");
	}
	else if (signo == SIGABRT)//pee没测试触发出来
	{
		/*
		1.调用 abort() 函数
		2.断言失败 (assert)
		3.内存分配错误等
		*/
		fprintf(fp, "codedump|%d", time(NULL));
		dzlog_info("sig_handler SIGABRT");
	}

	// 3. 获取并打印调用栈
	void* buffer[128]; // 用于存储调用栈地址的数组
	int nptrs = backtrace(buffer, 128); //获取当前调用栈
	dzlog_info("Call stack depth: %d", nptrs);
	// 将地址转换为可读的字符串
	char** strings = backtrace_symbols(buffer, nptrs);
	if (strings == NULL) {
		dzlog_error("错误: backtrace_symbols 失败");
		//goto cleanup;
	}

	// 逐行打印调用栈信息
	for (int i = 0; i < nptrs; i++) {
		dzlog_info("#%-2d %s", i, strings[i]);
	}
	free(strings); // 释放 backtrace_symbols 分配的内存

	fclose(fp);
	exit(signo);
}
 
int main(int argc, char **argv)
{
	int ret = 0;
	memset(LogLevel, 0, sizeof(LogLevel));
	sprintf(LogLevel, "LOG_WARNING");
	dzlog_init("./conf/zlog.conf", "GetIoT");

	if (snowflake_init(&sf, 1) != 0) {
		fprintf(stderr, "Invalid worker ID. Must be 0-%lu\n", MAX_WORKER_ID);
	}

	g_st_model_ctl.appModules = 0;
	g_st_model_ctl._4gModules = 1;

	// 开启自检线程，检查某些功能模块是否有。如appm start   self_checking
	pthread_t tid_self_checking;
	ret = pthread_create(&tid_self_checking, NULL, self_checking_thread, NULL);
	if (ret != 0)
	{
		dzlog_error("pthread_create self_checking_thread error\n");
	}
	// 自检线程end

	pthread_t tid_iotInfo;
	ret = pthread_create(&tid_iotInfo, NULL, iotInfo_thread, NULL);
	if (ret != 0)
	{
		dzlog_error("iotInfo_thread error\n");
		return;
	}

	// ini配置文件初始化
	if (config_init(&ini, &iniMqtt, &iniRule))
	{
		dzlog_error("config_init error\n");
	}
	else
	{
		dzlog_info("config_init succ");
	}
 
	struct sigaction sa;
	sa.sa_handler = sig_handler;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;
	sigaction(SIGINT, &sa, NULL);
	sigaction(SIGILL, &sa, NULL);
	sigaction(SIGFPE, &sa, NULL);
	sigaction(SIGSEGV, &sa, NULL);
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGABRT, &sa, NULL);

	// 管理模块
	// 1可适配接入外部组件，例如安全组件；
	// 2内部功能初始化，并设置全局回调函数（登录、发送消息、接收消息、功能处理...）；
	// 3管理模块，初始化各个协议对象；
	// 4数据内存模块，redis/db/队列。
	manage_control();
	// 程序启动时调用需要执行的shell
	commond_init_run();
	//   调度层:可兼容mqtt、rtp、rtsp、GB、私有协议
	dispach_proc();
	
	// 等待信号并处理
	while (1)
	{
		wiat_for_signal();
	}

	iniparser_freedict(ini);
	iniparser_freedict(iniMqtt);
	iniparser_freedict(iniRule);
	freeConfTerminalIni();
	manage_free();

	return 0;
}
